<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>期约和异步</title>
</head>
<body>
    <pre>
        await 是期待，等候的意思。
        async 是异步，asynchronous的前缀
    </pre>
</body>
<script>
    /* pending  fullfilled(resolved) rejected*/
    let p = new Promise((res,rej)=>{
        // setTimeout(() => {
        //     res(1)
        // }, 1);
        console.log('开始执行handle')
        res(2)
    }),
    p1 = Promise.resolve(1)
    ,p2= Promise.resolve(2)
    ,p3 = Promise.resolve(3)
    ,p5 = Promise.reject(5);
    p.then(()=>{
        console.log(p)
        // return Promise.resolve(2)
    }, ()=> {}).then((n)=>{console.log(n,1)})
    p.then(()=>{
        return 2
    }).then((n)=>{console.log(n,2)}).catch(()=> {})

    p.then(2).then((n)=>{console.log(n,3)})
    
    console.log( '全部测试代码写完')
    // Promise.reject(2)
    // new Promise((res,rej)=>{rej(2)})
    // 传给then()的任何非函数参数会被忽略，如果想只传rej,可以这样then(null,rej)
    /* 调用then(cb)会返回一个期约示例 这个期约实例就等于Promise.resolve(agr) agr就是cb函数的返回值 如果cb不是函数 那么会把前一个期约的返回值传进去 */
    Promise.all([p1,p2,p3])// 全部解决之后返回一个期约，期约的返回值是迭代数组，如果有期约被拒，返回的的是第一个被拒的理由
    Promise.race([p1,p2,p3]) //只要有一个 的状态落定就返回它的期约

    /* 在函数定义前加 async 关键字 就是异步函数，如果这个函数有 return 那么return 的值会被包装为期约,return 前的部分仍是同步
    但是 return之前 同步的 错误无法被catch 
    可以被catch,只要是异步的 ；
    */
    async function fn(){Promise.resolve('err') ;return Promise.reject('res')}
    fn().then(console.log).catch(console.log) //这个执行在p  之前 原因是 p本身就是期约但内部又有一层定时
    /*await 关键字 只能出现在 异步函数的定义中 await后后面的值解决后 才会执行下一行代码
    异步函数是可以捕获异常的 但是await 后面的期约异常 也可以通过catch捕获*/
    const   prej = Promise.reject('ject');
/* 直接调用Promise.reject() 而不对其进行接下来的处理 ， 是会直接走 console.error */
    async function f111(){
        console.log(11111);
        
        // let res = await prej ;   // 被拒 下一行代码执行不了，直接走到了catch ,也就是说
        // await 等待的是兑现， 兑现不了 就会一直等待,但是catch流的仍可走通
        try {
            let res = await prej ;
            console.log(res,'prej');
        }catch(e){
            console.log('err preje', e)
        }
        // let resp5 =   await p5;
          try{
              await p5
          }catch(e){
            console.log(e,'p5')
          }

          return "fullfilled" //没执行因为这个期约拒绝了，并且把拒绝理由传出去了，所以应该提前捕获，成功才会执行这一行
    }
    f111().then((s)=> console.log(s,'s'),(e)=>console.log(e,'err'))
    // 顺便在这里写一下节流 ，节流的背景 f1 触发了就会触发f2 现在不想让f2触发的那么频繁，f1不是我们能控制的，
    // 节流必然有个最小时间间隔， 在这个时间间隔内将不会重复触发f2 ，  首先都是在f1触发时设置一个定时器m秒后执行f2,
    // 时间间隔不超过m时  清除之前的定时器 设置新的
    function throttle(){
        let stamp = 0;
        let  timer
        return  function() {

            if (performance.now() - stamp < 500 || stamp === 0){
                stamp = performance.now() ;
                timer && clearTimeout(timer) ;
            }else {
                stamp = 0 ;
            }
            timer = setTimeout(() => {
                cb() ;
                clearTimeout(timer) ;
            }, 500);
        }
    }
</script>
</html>